package cn.edu.cug.cs.gtl.plugins.catalog.tree;

import cn.edu.cug.cs.gtl.apis.ui.AbstractApplication;
import cn.edu.cug.cs.gtl.apis.ui.actions.AbstractAction;
import cn.edu.cug.cs.gtl.apis.ui.datake.DatakeApp;
import cn.edu.cug.cs.gtl.apis.ui.datake.DatakeFrame;
import cn.edu.cug.cs.gtl.apis.ui.datake.catalogtree.CatalogTree;
import cn.edu.cug.cs.gtl.apis.ui.datake.catalogtree.JTreeTools;
import cn.edu.cug.cs.gtl.apis.ui.tree.TreeNodeData;
import cn.edu.cug.cs.gtl.plugins.catalog.utils.HdfsFileUtils;
import cn.edu.cug.cs.gtl.protos.*;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import java.awt.event.ActionEvent;
import java.io.File;
import java.util.*;

public class UpLoadDir extends AbstractAction {
    String hdfsPath = "hdfs://202.114.198.141:8020/data/lake/";    // 设置上传的hdfs文件路径
    String hdfsUri = "hdfs://202.114.198.141:8020/";
    File folder;

    @Override
    public void initialize(AbstractApplication theApp) {
        this.theApp = theApp;
        ResourceBundle resourceBundle = ResourceBundle.getBundle("catalog-resource", Locale.getDefault());

        name = "上传文件夹";
        menuItem.setText(name);
        menuItem.addActionListener(this);
        ((CatalogTree) (getDatakeFrame().getCatalogPanel().getTreeComponent())).getCatalogNodePopupMenu().add(menuItem);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        JFileChooser fileChooser = new JFileChooser();
        fileChooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
        int option = fileChooser.showOpenDialog(null);

        //获取用户选择的文件夹
        if (option == JFileChooser.APPROVE_OPTION) {
            folder = fileChooser.getSelectedFile();
        } else {
            System.err.println("用户取消了选择");
            return;
        }

        //文件夹合法性检测
        if (!checkFolder(folder)) {
            JOptionPane.showMessageDialog(null, "上传的文件夹不合法.");
            return;
        }

        // 获取选中的树节点
        DefaultMutableTreeNode selectedTreeNode = getMouseSelectedNode();
        if (selectedTreeNode == null) {
            JOptionPane.showMessageDialog(null, "请选择一个目录节点.");
            return;
        }

        // 从选中节点向上遍历到根节点，构建路径
        StringBuilder pathBuilder = new StringBuilder();
        buildPathFromRoot(selectedTreeNode, pathBuilder);

        // 构建完整的HDFS路径
        String fullHdfsPath = hdfsPath + pathBuilder + "/" + folder.getName() + "/";
        // 将文件夹上传至HDFS并将元数据写入到数据库
        DataCatalog dataCatalog = (DataCatalog) ((TreeNodeData) (selectedTreeNode.getUserObject())).getRefObject();
        try {
            HdfsFileUtils.uploadFile(dataCatalog.getName(), hdfsUri, folder.getAbsolutePath(), fullHdfsPath);
        } catch (Exception ex) {
            JOptionPane.showMessageDialog(null, "上传失败: " + ex.getMessage());
            throw new RuntimeException(ex);
        }

        // 在JTree目录树中显示文件夹目录结构
        CatalogTree tree = (CatalogTree) getDatakeFrame().getCatalogPanel().getTreeComponent();

        //移除鼠标选中节点的所有子节点
        selectedTreeNode.removeAllChildren();
        //通知树模型节点结构已修改
        DefaultTreeModel treeModel = (DefaultTreeModel) tree.getModel();
        treeModel.nodeStructureChanged(selectedTreeNode);
        //重新从数据库中加载树结构信息
        JTreeTools.createBranch(tree, selectedTreeNode);
    }

    // 辅助方法，用于从根节点到选中节点构建路径
    private void buildPathFromRoot(DefaultMutableTreeNode node, StringBuilder pathBuilder) {
        // 确保StringBuilder以正确的分隔符开始
        if (pathBuilder.length() > 0) {
            pathBuilder.insert(0, "/");
        }

        // 向上遍历到根节点
        while (node != null&&node.getParent()!=null) {
            Object userObject = ((TreeNodeData) node.getUserObject()).getRefObject();
            if (userObject instanceof DataCatalog) {
                // 假设TreeNodeData的getRefObject方法返回节点名称
                String nodeName = ((DataCatalog) userObject).getName().toString();
                pathBuilder.insert(0, nodeName); // 将节点名称添加到路径的前面
            } else if (userObject instanceof DataGroup) {
                String nodeName = ((DataGroup) userObject).getName().toString();
                pathBuilder.insert(0, nodeName);
            } else if (userObject instanceof DataItem) {
                String nodeName = ((DataItem) userObject).getName().toString();
                pathBuilder.insert(0, nodeName);
            } else {
                throw new RuntimeException("未知的节点类型.");
            }
            node = (DefaultMutableTreeNode) node.getParent(); // 移动到父节点
        }
    }

    //获取鼠标选中节点
    private DefaultMutableTreeNode getMouseSelectedNode() {
        CatalogTree tree = (CatalogTree) getDatakeFrame().getCatalogPanel().getTreeComponent();
        return (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
    }

    //文件夹合法性检测
    private static boolean checkFolder(File folder) {
        File[] files = folder.listFiles();
        if (files == null || files.length == 0) {
            return false; // 空文件夹不满足条件
        }

        boolean hasFiles = false;
        boolean hasFolders = false;

        for (File file : files) {
            if (file.isDirectory()) {
                hasFolders = true;
                // 递归检查子文件夹
                if (!checkFolder(file)) {
                    return false;
                }
            } else {
                hasFiles = true;
            }
        }
        return !(hasFiles && hasFolders); // 如果同时包含文件和文件夹则不满足条件
    }

    public DatakeFrame getDatakeFrame() {
        return (DatakeFrame) (((DatakeApp) theApp).getMainFrame());
    }
}
